import {
  ElMessage,
  ElMessageBox,
  ElLoading,
  type ElMessageBoxOptions,
  type MessageOptions,
} from 'element-plus'
import 'element-plus/es/components/message-box/style/css'
import 'element-plus/es/components/message/style/css'
import 'element-plus/es/components/loading/style/css'
import { noop } from '..'

export const showLoading = (text?: string) => {
  return ElLoading.service({
    text,
  })
}

export const closeAllMessageBox = () => {
  ElMessageBox.close()
}

export type UIShowMessageType = 'success' | 'warning' | 'info' | 'error'

export const showMessage = (
  opt: MessageOptions | string,
  type?: UIShowMessageType
) => {
  const options: MessageOptions =
    typeof opt === 'string' ? { message: opt } : opt
  if (type !== undefined) options.type = type
  ElMessage(options)
}

export const showInfo = (opt: MessageOptions | string) =>
  showMessage(opt, 'info')

export const showSuccess = (opt: MessageOptions | string) =>
  showMessage(opt, 'success')

export const showWarning = (opt: MessageOptions | string) =>
  showMessage(opt, 'warning')

export const showError = (opt: MessageOptions | string) =>
  showMessage(opt, 'error')

export type ElMessageBoxButtonType =
  | 'default'
  | 'primary'
  | 'success'
  | 'warning'
  | 'info'
  | 'danger'
export interface ElMessageBoxOptionsExtended extends ElMessageBoxOptions {
  confirmButtonType?: ElMessageBoxButtonType
  cancelButtonType?: ElMessageBoxButtonType
}

const extendElMessageBoxOptions = (opt: ElMessageBoxOptionsExtended) => {
  const options: ElMessageBoxOptionsExtended = { ...opt }
  if (options.confirmButtonType) {
    options.confirmButtonClass = 'el-button--' + options.confirmButtonType
  }
  if (options.cancelButtonType) {
    options.cancelButtonClass = 'el-button--' + options.cancelButtonType
  }
  return options
}

export const showAlert = async (
  opt: ElMessageBoxOptionsExtended | string,
  title?: string
) => {
  const options = extendElMessageBoxOptions(
    typeof opt === 'string' ? { message: opt } : opt
  )
  if (title) options.title = title
  if (typeof options.title === 'undefined') {
    options.title = '提示'
  }
  try {
    await ElMessageBox(options)
  } catch {
    // ignore
  }
}

export type UIShowConfirmOptions = Omit<
  ElMessageBoxOptionsExtended,
  'beforeClose' | 'callback'
>

export const showConfirm = <T = any>(
  opt: UIShowConfirmOptions | string,
  onOk: (inputValue?: string) => T | Promise<T>
): Promise<T | undefined> => {
  const options = extendElMessageBoxOptions(
    typeof opt === 'string' ? { message: opt } : opt
  )
  if (typeof options.title === 'undefined') {
    options.title = '提示'
  }
  if (typeof options.type === 'undefined') {
    options.type = 'warning'
  }
  return new Promise((resolve, reject) => {
    ElMessageBox[options.showInput ? 'prompt' : 'confirm'](options.message, {
      ...options,
      beforeClose: async (a, i, done) => {
        if (a !== 'confirm') {
          done()
          return resolve(undefined)
        }
        try {
          i.confirmButtonLoading = true
          const r = await onOk(i.inputValue)
          done()
          resolve(r)
        } catch (e: any) {
          return reject(e)
        } finally {
          i.confirmButtonLoading = false
        }
      },
    }).catch(noop)
  })
}
